"""Controller module"""

import wx
from ProjectWizardView import ProjectWizardView
import project.project as project
import os
import GUIconfig
import threading
from GeneFinderUI import GeneFinderUI
from project.errors import ProjectError, ProjectFileNotFoundError
from epiguilib import run_in_thread_with_progressbar
import validator 
import time 

MONETDB_CHOICE = 1
SQLITE_CHOICE = 0

#TASK_COMPLETE_EVT_ID = 1
#TASK_RUNNING_EVT_ID = 2
#
#
#class BackgroundThread(threading.Thread):
#    
#    def __init__(self, parent, func, *args):
#        threading.Thread.__init__(self)
#        self.func = func
#        self.args = args
#        self._parent = parent
#    
#    def progress(self, progress):
#        evt = BackgroundEvent(myEVT_BG_TASK, TASK_RUNNING_EVT_ID, "running", progress)
#        wx.PostEvent(self._parent, evt)
#            
#    def run(self):
#        output = self.func(*self.args, callback=self.progress)
#        evt = BackgroundEvent(myEVT_BG_TASK, TASK_COMPLETE_EVT_ID, output, 100)
#        wx.PostEvent(self._parent, evt)
#
##EVT_DB_TASK_COMPLETE = wx.NewId()
#
#myEVT_BG_TASK = wx.NewEventType()
#EVT_BG = wx.PyEventBinder(myEVT_BG_TASK, 1)
#
#class BackgroundEvent(wx.PyCommandEvent):
#    def __init__(self, etype, eid, msg=None, progress=None):
#        """Init Result Event."""
#        
#        wx.PyCommandEvent.__init__(self, etype, eid)
#        self.SetEventType(myEVT_BG_TASK)
#        self.msg = msg
#        self.progress = progress
#        self.eid = eid
#        
#        
#    def GetMsg(self):
#        return self.msg
#
#    def GetProgress(self):
#        return self.progress
#    
#    def task_complete(self):
#        return (TASK_COMPLETE_EVT_ID == self.eid)


class ProjectWizard( ProjectWizardView ):
    title = ""
    location = ""
    def __init__( self, parent ):
        ProjectWizardView.__init__(self, parent, style = wx.DIALOG_NO_PARENT)
        #self.load_recent_projects()
        #self.Bind( EVT_BG, self.OnDatabaseUpdated )
        
        self.project_settings_page.content.project_location.SetPath(os.path.expanduser("~"))
        
        self.genotypes_imported = False
        self.phenotypes_imported = False
        self.classes_imported = False
        
        self.import_thread = None
        
        self.import_genotypes_page.Enable(False) # disable until DB is started
        
        
    def run_create_prj_wizard(self, page=None):
        start_page = self.project_settings_page
        if page:
            start_page = page 
        self.RunWizard(start_page)
        self.Destroy()
    
    
    def run_import_partition_wiz(self):    
        self.Unbind(wx.wizard.EVT_WIZARD_CANCEL) # dont call the usual cancel handler
        self.Unbind(wx.wizard.EVT_WIZARD_FINISHED) # dont call the usual finished handler
        
        self.RunWizard(self.import_classes_page)    
        
        self.Destroy()
    
    
    def set_next_button(self, bool_value):
        self.FindWindowById(wx.ID_FORWARD).Enable(bool_value)
    
    def set_backward_button(self, bool_value):
        self.FindWindowById(wx.ID_BACKWARD).Enable(bool_value)
    
   
    def import_view_start(self):
        "nothing"
        #self.GetCurrentPage().Enable(False)
                
    def import_view_done(self, import_succesful):
        if import_succesful:
        #self.import_page.Destroy()
            self.GetCurrentPage().Enable(True)
            self.GetCurrentPage().content.message.SetLabel("Import is complete.")
        
            self.set_next_button(True)
    
        else:
            self.GetCurrentPage().Enable(True)
            self.GetCurrentPage().content.message.SetLabel("Import was cancelled.")
            
            if self.GetCurrentPage() == self.import_genotypes_page:
                self.genotypes_imported = False 
            if self.GetCurrentPage() == self.import_phenotypes_page:
                self.phenotypes_imported = False
            if self.GetCurrentPage() == self.import_classes_page:
                self.classes_imported = False
        
    
    
    
    # ----- Event handlers --------------
     
             
     
    def OnGenotypeFileSelected(self, event ):
        file_path = event.GetEventObject().GetPath()
        #db_thread = BackgroundThread(self, project.import_genotypes, file_path)
        #db_thread.start()
        print self.GetCurrentPage()
        self.import_thread = run_in_thread_with_progressbar(project.import_genotypes, (file_path,), self.OnDatabaseUpdated, self, "Importing genotypes.")
        
        #self.import_page = self.import_status_page(self)
        project.set_project_info("genotype_file", file_path)
        self.genotypes_imported = True
        self.import_view_start()
        
    def OnPhenotypeFileSelected(self, event ):
        file_path = event.GetEventObject().GetPath()
        #db_thread = BackgroundThread(self, project.import_phenotypes, file_path)
        #db_thread.start()
        self.import_thread = run_in_thread_with_progressbar(project.import_phenotypes, (file_path,), self.OnDatabaseUpdated, self, "Importing phenotypes.")
        #self.import_page = self.import_status_page(self)
        project.set_project_info("phenotype_file", file_path)
        self.phenotypes_imported = True
        self.import_view_start()
        
    
    def OnPartionRadioBtn(self, event):
        self.import_classes_page.content.partition_text.Enable(True)
        self.import_classes_page.content.partition_file_picker.Enable(True)
        self.import_classes_page.content.partition_threshold.Enable(True)
        self.import_classes_page.content.partition_threshold_label.Enable(True)
        
        self.import_classes_page.content.class_text.Enable(False)
        self.import_classes_page.content.class_file_picker.Enable(False)
        
        
    def OnClassRadioBtn(self, event):
        self.import_classes_page.content.partition_text.Enable(False)
        self.import_classes_page.content.partition_file_picker.Enable(False)
        self.import_classes_page.content.partition_threshold.Enable(False)
        self.import_classes_page.content.partition_threshold_label.Enable(False)
        
        self.import_classes_page.content.class_text.Enable(True)
        self.import_classes_page.content.class_file_picker.Enable(True)
     
     
    def OnImportPartitionBtn(self, event):
        file_path = ""
        if self.import_classes_page.content.partition_radio_button.GetValue():
            file_path = self.import_classes_page.content.partition_file_picker.GetPath()
            if not (file_path and os.path.exists(file_path)):
                dlg = wx.MessageDialog(self, "Please select a valid file.", "Error.", wx.ICON_ERROR)
                dlg.ShowModal()
                #event.Veto()
                return False            
            
            threshold_str = self.import_classes_page.content.partition_threshold.GetValue()    
            try :
                validator.validate_partition_threshold(threshold_str)
            except Exception, e:
                dlg = wx.MessageDialog(self, str(e), "Error.", wx.ICON_ERROR)
                dlg.ShowModal()
                #event.Veto()
                return False     
            dlg = wx.MessageDialog(self, 'Process partition file with threshold value %s?' % threshold_str, 'Please Confirm', wx.YES_NO |
                                   wx.YES_DEFAULT | wx.ICON_QUESTION)        
            if dlg.ShowModal() != wx.ID_YES:
                #event.Veto()
                return False
            
            partition_threshold = float(threshold_str)
               
            self.import_thread = run_in_thread_with_progressbar(project.import_class_by_partition, (file_path, partition_threshold) , self.OnDatabaseUpdated, self, "Importing partition.")
        
        if self.import_classes_page.content.class_radio_button.GetValue():
            file_path = self.import_classes_page.content.class_file_picker.GetPath()    
            if not (file_path and os.path.exists(file_path)):
                dlg = wx.MessageDialog(self, "Please select a valid file.", "Error.", wx.ICON_ERROR)
                dlg.ShowModal()
                #event.Veto()
                return False            
            
            self.import_thread = run_in_thread_with_progressbar(project.import_classes, (file_path,) , self.OnDatabaseUpdated, self, "Importing classes.")
        
        project.set_project_info("class_file", file_path)
        self.classes_imported = True
        self.import_view_start()


        
#    def OnPartitionFileSelected(self, event ):
#        file_path = event.GetEventObject().GetPath()
#        threshold_str = self.import_classes_page.content.partition_threshold.GetValue()
#        #print file_path, threshold
#        
#        try :
#            validator.validate_partition_threshold(threshold_str)
#        except Exception, e:
#            dlg = wx.MessageDialog(self, str(e), "Error.", wx.ICON_ERROR)
#            dlg.ShowModal()
#            event.Veto()
#            return False 
#        
#        dlg = wx.MessageDialog(self, 'Process partition file with threshold value %s?' % threshold_str, 'Please Confirm', wx.YES_NO |
#                               wx.YES_DEFAULT | wx.ICON_QUESTION)        
#        if dlg.ShowModal() != wx.ID_YES:
#            event.Veto()
#            return False
#            
#        partition_threshold = float(threshold_str)
#        
#        run_in_thread_with_progressbar(project.import_class_by_partition, (file_path, partition_threshold) , self.OnDatabaseUpdated, self, "Importing partition.")
#
#        project.set_project_info("class_file", file_path)
#        self.classes_imported = True
#        self.import_view_start()
#        
#                
#    def OnClassFileSelected(self, event ):
#        file_path = event.GetEventObject().GetPath()
#        #db_thread = BackgroundThread(self, project.import_classes, file_path)
#        #db_thread.start()
#        
#        run_in_thread_with_progressbar(project.import_classes, (file_path,) , self.OnDatabaseUpdated, self, "Importing classes.")
#        
#        #self.import_page = self.import_status_page(self)
#        project.set_project_info("class_file", file_path)
#        self.classes_imported = True
#        self.import_view_start()
#                
    def OnWizardFinished(self, event):
        gf = GeneFinderUI(self.Parent)
        gf.Show()
    
    def OnWizardCancel(self, event):
        if self.import_thread:
            self.import_thread.stop()
            self.import_thread.join()
            
        if project.project_selected():
            print "Cancelling and deleting incomplete project."
            project.remove_current_project()
            

    
    
    def OnWizardChangedPage(self, event):
        """
        This event fires after the page has changed
        """
        # changed forward to classes, phenotypes or genotypes page
        if event.GetPage() in [self.import_classes_page, self.import_phenotypes_page, self.import_genotypes_page] and event.GetDirection():  
            self.set_next_button(False)
        
        # these if's are for enabling the next button if the file is already imported before going backwards in the wizard
        if event.GetPage() == self.import_genotypes_page and self.genotypes_imported :
            self.set_next_button(True)
        
        if event.GetPage() == self.import_phenotypes_page and self.phenotypes_imported :
            self.set_next_button(True)
        
        if event.GetPage() == self.import_classes_page and self.classes_imported :
            self.set_next_button(True)
              
        # changed backwards to classes, phenotypes or genotypes page. files are already imported so enabled next button
#        if event.GetPage() in [self.import_classes_page, self.import_phenotypes_page, self.import_genotypes_page] and not event.GetDirection():  
#           self.set_next_button(True)
        
        #changed to settings page going backwards
        if self.project_settings_page == event.GetPage() and not event.GetDirection():
            self.set_next_button(True)
            self.genotypes_imported = False
            self.phenotypes_imported = False
            self.classes_imported = False
            self.import_genotypes_page.content.message.SetLabel("Import genotypes")
            self.import_phenotypes_page.content.message.SetLabel("Import phenotypes")
            self.import_classes_page.content.message.SetLabel("Import partition")
            
            if project.using_monetdb():
                run_in_thread_with_progressbar(func=project.kill_db, args=(), callback=None, host_gui_object=self, msg="stopping db")
            time.sleep(2) # wait for the daemon to shut down before removing the files
            
            project.remove_current_project()
            print "removing incomplete project."
            
            
        # this means that we started on the classes page
        if self.import_classes_page == event.GetPage() and not self.genotypes_imported and not self.phenotypes_imported:
            self.set_backward_button(False)         
            
        print "new page"
    
    def OnWizardChangingPage(self, event):
        """
        This event fires just before the page changes
        """
                
        if self.project_settings_page == event.GetPage() and event.GetDirection(): # when changing forward from the start page
            print "changing from start page"
            settings_page = event.GetPage()
            p_title = settings_page.content.project_title.GetValue()
            p_location = settings_page.content.project_location.GetPath()
            path = os.path.join(p_location, p_title)
            dbms_type = settings_page.content.dbms_choice.GetSelection() 
            print "DBMS type", dbms_type
            try : 
                project.validate_project_dir(path)
                self.title = p_title
                self.location = p_location
                print "creating new project"
                project.create_project(self.location, self.title)
                
            except ProjectError, e: 
                #print e
                settings_page.content.message.SetLabel(str(e))
                event.Veto()
                return False
            except OSError, e: 
                #print e
                settings_page.content.message.SetLabel(str(e))
                event.Veto()
                return False
            
            settings_page.content.message.SetLabel("") # reset the status message
            
            if dbms_type == 0: # 0 for sqlite 
                project.set_project_info("dbms", project.DBMS_TYPE_SQLITE)
            else:   # 1 for monetdb
                project.set_project_info("dbms", project.DBMS_TYPE_MONETDB)
                
            run_in_thread_with_progressbar(func=project.start_db, args=(), callback=self.OnDatabaseStarted, host_gui_object=self, msg="starting db")
        
            #changing to settings page going backwards
        if self.import_genotypes_page == event.GetPage() and not event.GetDirection():
            dlg = wx.MessageDialog(self, 'Are you sure you want to start over?', 'Please Confirm', wx.YES_NO |
                               wx.YES_DEFAULT | wx.ICON_QUESTION)        
            if dlg.ShowModal() == wx.ID_NO:
                event.Veto()
                return False
        
        print "changing page"
            

    def OnDatabaseStarted(self, event):
        out = event.GetOutput()
        print out
        (succes, msg) = out 
        if not succes:
            dlg = wx.MessageDialog(self, msg, "Error.", wx.ICON_ERROR)
            dlg.ShowModal()
            return
        else:
            self.import_genotypes_page.Enable(True)
            
    
        
    def OnDatabaseUpdated(self, event):
        if event.task_complete():
            print "db ready"
            success = event.GetOutput()
            print "success:", success
            self.import_view_done(success)

        #else:
        #    progress_percentage = event.GetProgress()
        #    self.import_page.progress_gauge.SetValue(progress_percentage)


if __name__ == "__main__":
    app = wx.App(False)  # Create a new app, don't redirect stdout/stderr to a window.
    project.open_project("/home/benjamin/my_project4/my_project4.epiprj")
    w = ProjectWizard(parent=None) # A Frame is a top-level window.
    #w.Show(True)     # Show the frame.
    print "Starting wizard"
    w.run_create_prj_wizard(page=w.import_classes_page)
    app.MainLoop()
   
